package com.wanli.controller;
import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wanli.common.Result;
import com.wanli.domain.entity.Menu;
import com.wanli.domain.entity.RoleMenu;
import com.wanli.domain.entity.User;
import com.wanli.domain.dto.MenuDto;
import com.wanli.service.MenuService;
import com.wanli.service.RoleMenuService;
import com.wanli.service.UserService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import com.wanli.common.BaseController;

import java.security.Principal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 *  菜单控制器
 * </p>
 *
 * @author Byterain
 * @since 2023-12-06
 */
@RestController
@RequestMapping("/menu")
public class MenuController extends BaseController {
    @Autowired
    MenuService menuService;
    @Autowired
    UserService userService;
    @Autowired
    RoleMenuService roleMenuService;

    @PreAuthorize("hasAuthority('sys:role:perm')")
    @PostMapping("/perm/{roleId}")
    public Result perm(){
        return null;
    }

    //根据菜单的id查询该菜单的详细数据
    @GetMapping("/info/{id}")
    public Result info(@PathVariable Long id){
        Menu menu = menuService.getById(id);  //IService  getById()
        return Result.success(menu);
    }

    //编辑菜单 更新菜单数据方法
    @PreAuthorize("hasAuthority('sys:menu:update')")
    @PostMapping("/update")
    public Result update(@RequestBody Menu menu){
        menu.setUpdated(LocalDateTime.now());
        menuService.updateById(menu);
        return Result.success("菜单数据更新成功");
    }

    //新建菜单保存方法,vue端请求的参数是JSON对象，方法接收必须使用@RequestBody
    @PreAuthorize("hasAuthority('sys:menu:save')")
    @PostMapping("/save")
    public Result save(@RequestBody Menu menu){
        //设置菜单的录入时间为 当前时间
        menu.setCreated(LocalDateTime.now());
        menuService.save(menu);   //调用IService 实现 save()
        return Result.success("菜单数据保存成功");
    }


    @GetMapping("/delete/{id}")
    @PreAuthorize("hasAuthority('sys:menu:delete')")
    @Transactional
    public Result delete(@PathVariable("id") Long id){
        //查询删除菜单id下面是否还具有子菜单
        //QueryWrapper<Menu> qw = new QueryWrapper<>();
        //qw.eq("parent_id",id);

        //IService : count() 求记录数  查询当前删除id菜单下面有多少条子菜单
        int count = menuService.count(new QueryWrapper<Menu>().eq("parent_id",id));
        if(count>0){
            return Result.fail("请先删除该菜单下面的子菜单数据");
        }else{

            //*****先进行 与该菜单id 相关的用户数据查询(清除redis)，然后再删除菜单:
            //清空Redis中用户的权限字符串。重置用户权限。
            userService.clearUserAuthorityInfoByMenuId(id);

            //IService : removeById()根据菜单id删除菜单数据.
            menuService.removeById(id);
            //菜单和角色有关联： sys_role_menu  删除关系表中 menu_id=删除菜单id
            roleMenuService.remove(new QueryWrapper<RoleMenu>().eq("menu_id",id));

            return Result.success("菜单删除成功");
        }
    }

    //菜单管理界面表格：获得菜单数据
    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:menu:list')")
    public Result list(){
        List<Menu> tree = menuService.tree();
        return Result.success(tree);
    }


    //SpringSecurity如果需要再Controller的方法中获得登录用户名，可以使用Principal
    @GetMapping("/nav")
    public Result nav(Principal principal){
        //查询菜单数据，需要当前登录用户名。
        String username = principal.getName();  //直接从Security中取出登录用户名
        List<MenuDto> menuDtoList = menuService.getCurrentUserNav(username);

        //构建返回Vue权限信息
        User user = userService.getUserByUsername(username);
        //查询当前用户的权限字符串
        String authorityInfo = userService.getUserAuthorityInfo(user.getId());
        //将权限字符串按照逗号分割，转换为数组
        String[] authoritys = StringUtils.tokenizeToStringArray(authorityInfo, ",");

        return Result.success(MapUtil.builder().put("nav",menuDtoList).put("authoritys",authoritys).map());
    }
}
